{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Tce3stUlHN0L"
      },
      "source": [
        "##### Copyright 2025 Google LLC."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "cellView": "form",
        "id": "tuOe1ymfHZPu"
      },
      "outputs": [],
      "source": [
        "# @title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "GAsiP4mohC2_"
      },
      "source": [
        "# Gemini API: JSON Mode Quickstart\n",
        "\n",
        "<a target=\"_blank\" href=\"https://colab.research.google.com/github/google-gemini/cookbook/blob/main/quickstarts/JSON_mode.ipynb\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" height=30/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "lF6sWVRGQ_bi"
      },
      "source": [
        "The Gemini API can be used to generate a JSON output if you set the schema that you would like to use.\n",
        "\n",
        "Two methods are available. You can either set the desired output in the prompt or supply a schema to the model separately."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "857d8bf104ed"
      },
      "source": [
        "### Install dependencies"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "qLuL9m7KhvxR"
      },
      "outputs": [],
      "source": [
        "%pip install -U -q \"google-genai>=1.0.0\""
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "B-axqBTM8Lbd"
      },
      "source": [
        "### Configure your API key\n",
        "\n",
        "To run the following cell, your API key must be stored in a Colab Secret named `GOOGLE_API_KEY`. If you don't already have an API key, or you're not sure how to create a Colab Secret, see [Authentication ![image](https://storage.googleapis.com/generativeai-downloads/images/colab_icon16.png)](../quickstarts/Authentication.ipynb) for an example."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {
        "id": "d6lYXRcjthKV"
      },
      "outputs": [],
      "source": [
        "from google.colab import userdata\n",
        "from google import genai\n",
        "\n",
        "GOOGLE_API_KEY = userdata.get('GOOGLE_API_KEY')\n",
        "client = genai.Client(api_key=GOOGLE_API_KEY)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "hD3qXcOTRD3z"
      },
      "source": [
        "## Set your constrained output in the prompt\n",
        "\n",
        "For this first example just describe the schema you want back in the prompt:\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {
        "id": "K8ezjNb0RJ6Y"
      },
      "outputs": [],
      "source": [
        "prompt = \"\"\"\n",
        "  List a few popular cookie recipes using this JSON schema:\n",
        "\n",
        "  Recipe = {'recipe_name': str}\n",
        "  Return: list[Recipe]\n",
        "\"\"\""
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "4071a6143d31"
      },
      "source": [
        "Now select the model you want to use in this guide, either by selecting one in the list or writing it down. Keep in mind that some models, like the 2.5 ones are thinking models and thus take slightly more time to respond (cf. [thinking notebook](./Get_started_thinking.ipynb) for more details and in particular learn how to switch the thiking off).\n",
        "\n",
        "Then activate JSON mode by specifying `respose_mime_type` in the `config` parameter:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {
        "id": "ggudoxK8RMlb"
      },
      "outputs": [],
      "source": [
        "MODEL_ID = \"gemini-2.5-flash\" # @param [\"gemini-2.5-flash-lite\", \"gemini-2.5-flash\", \"gemini-2.5-pro\",\"gemini-3-pro-preview\"] {\"allow-input\":true, isTemplate: true}\n",
        "\n",
        "raw_response = client.models.generate_content(\n",
        "    model=MODEL_ID,\n",
        "    contents=prompt,\n",
        "    config={\n",
        "        'response_mime_type': 'application/json'\n",
        "    },\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9TqoNg3VSMYB"
      },
      "source": [
        "Parse the string to JSON:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {
        "id": "b99ee66972f5"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[{'recipe_name': 'Chocolate Chip Cookies'}, {'recipe_name': 'Oatmeal Raisin Cookies'}, {'recipe_name': 'Peanut Butter Cookies'}, {'recipe_name': 'Sugar Cookies'}, {'recipe_name': 'Snickerdoodles'}]\n"
          ]
        }
      ],
      "source": [
        "import json\n",
        "\n",
        "response = json.loads(raw_response.text)\n",
        "print(response)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "1092c669169a"
      },
      "source": [
        "For readability serialize and print it:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {
        "id": "WLDPREpmSMu5"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[\n",
            "    {\n",
            "        \"recipe_name\": \"Chocolate Chip Cookies\"\n",
            "    },\n",
            "    {\n",
            "        \"recipe_name\": \"Oatmeal Raisin Cookies\"\n",
            "    },\n",
            "    {\n",
            "        \"recipe_name\": \"Peanut Butter Cookies\"\n",
            "    },\n",
            "    {\n",
            "        \"recipe_name\": \"Sugar Cookies\"\n",
            "    },\n",
            "    {\n",
            "        \"recipe_name\": \"Snickerdoodles\"\n",
            "    }\n",
            "]\n"
          ]
        }
      ],
      "source": [
        "print(json.dumps(response, indent=4))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "K9nIks0R-tIa"
      },
      "source": [
        "## Supply the schema to the model directly\n",
        "\n",
        "The newest models (1.5 and beyond) allow you to pass a schema object (or a python type equivalent) directly and the output will strictly follow that schema.\n",
        "\n",
        "Following the same example as the previous section, here's that recipe type:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "metadata": {
        "id": "JiIxKaLl4R0f"
      },
      "outputs": [],
      "source": [
        "import typing_extensions as typing\n",
        "\n",
        "class Recipe(typing.TypedDict):\n",
        "    recipe_name: str\n",
        "    recipe_description: str\n",
        "    recipe_ingredients: list[str]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vBlWzt6M-2oM"
      },
      "source": [
        "For this example you want a list of `Recipe` objects, so pass `list[Recipe]` to the `response_schema` field of the `config`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "metadata": {
        "id": "8oe-tL8MDGtx"
      },
      "outputs": [],
      "source": [
        "result = client.models.generate_content(\n",
        "    model=MODEL_ID,\n",
        "    contents=\"List a few imaginative cookie recipes along with a one-sentence description as if you were a gourmet restaurant and their main ingredients\",\n",
        "    config={\n",
        "        'response_mime_type': 'application/json',\n",
        "        'response_schema': list[Recipe],\n",
        "    },\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "metadata": {
        "id": "slYcVAcqaDQY"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[\n",
            "    {\n",
            "        \"recipe_name\": \"Lavender & White Chocolate Cloud Kisses\",\n",
            "        \"recipe_description\": \"Delicate lavender-infused meringue cookies, airily light and meltingly tender, are kissed with swirls of creamy white chocolate.\",\n",
            "        \"recipe_ingredients\": [\n",
            "            \"Egg whites\",\n",
            "            \"Sugar\",\n",
            "            \"Dried lavender\",\n",
            "            \"White chocolate\"\n",
            "        ]\n",
            "    },\n",
            "    {\n",
            "        \"recipe_name\": \"Smoked Paprika & Dark Chocolate Chili Sables\",\n",
            "        \"recipe_description\": \"A sophisticated blend of smoky paprika, intense dark chocolate, and a whisper of chili creates a captivating sweet and savory experience in a crisp sable cookie.\",\n",
            "        \"recipe_ingredients\": [\n",
            "            \"All-purpose flour\",\n",
            "            \"Unsalted butter\",\n",
            "            \"Dark chocolate\",\n",
            "            \"Smoked paprika\",\n",
            "            \"Chili powder\"\n",
            "        ]\n",
            "    },\n",
            "    {\n",
            "        \"recipe_name\": \"Matcha & Black Sesame Shortbread Petals\",\n",
            "        \"recipe_description\": \"Elegantly sculpted shortbread petals, vibrant with ceremonial matcha, offer a sublime earthy sweetness balanced by the nutty depth of toasted black sesame.\",\n",
            "        \"recipe_ingredients\": [\n",
            "            \"All-purpose flour\",\n",
            "            \"Unsalted butter\",\n",
            "            \"Sugar\",\n",
            "            \"Matcha powder\",\n",
            "            \"Black sesame seeds\"\n",
            "        ]\n",
            "    }\n",
            "]\n"
          ]
        }
      ],
      "source": [
        "print(json.dumps(json.loads(result.text), indent=4))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "239af844c650"
      },
      "source": [
        "It is the recommended method if you're using a compatible model."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5ef9efdb62d3"
      },
      "source": [
        "## Next Steps\n",
        "### Useful API references:\n",
        "\n",
        "Check the [structured ouput](https://ai.google.dev/gemini-api/docs/structured-output) documentation or the [`GenerationConfig`](https://ai.google.dev/api/generate-content#generationconfig) API reference for more details\n",
        "\n",
        "### Related examples\n",
        "\n",
        "* The constrained output is used in the [Text summarization](../examples/json_capabilities/Text_Summarization.ipynb) example to provide the model a format to summarize a story (genre, characters, etc...)\n",
        "* The [Object detection](../examples/Object_detection.ipynb) examples are using the JSON constrained output to uniiformize the output of the detection.\n",
        "\n",
        "### Continue your discovery of the Gemini API\n",
        "\n",
        "JSON is not the only way to constrain the output of the model, you can also use an [Enum](../quickstarts/Enum.ipynb). [Function calling](../quickstarts/Function_calling.ipynb) and [Code execution](../quickstarts/Code_Execution.ipynb) are other ways to enhance your model by either using your own functions or by letting the model write and run them."
      ]
    }
  ],
  "metadata": {
    "colab": {
      "name": "JSON_mode.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
